/* vim:set noet ts=4: */
/** 
 * scim-python
 * 
 * Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * $Id: $
 */
#include <Python.h>
#include "structmember.h"
#include "scim-python-attribute.h"

struct PyAttribute {
	PyObject_HEAD
	/* Type-specific fields go here. */
	Attribute attribute;
};

AttributeList
Attributes_FromTupleOrList (PyObject *object)
{
	int size;
	AttributeList attrs;
	
	if (object == NULL || object == Py_None)
		return attrs;

	if (PyTuple_Check (object)) {
		size = PyTuple_Size (object);
		for (int i = 0; i < size; i++) {
			attrs.push_back (Attribute_FromPyObject (PyTuple_GetItem (object, i)));
		}
	}
	else if (PyList_Check (object)) {
		size = PyList_Size (object);
		for (int i = 0; i < size; i++) {
			attrs.push_back (Attribute_FromPyObject (PyList_GetItem (object, i)));
		}
	}
	return attrs;
}

static PyObject *
PyAttribute_str (const PyAttribute* self)
{
	char buf[128];
	sprintf (buf, "Attribute (start=%d, length=%d, type=%d, value=%d)",
				self->attribute.get_start (), 
				self->attribute.get_length (), 
				self->attribute.get_type (),
				self->attribute.get_value ());

	return PyString_FromString (buf);
}

static PyObject *
PyAttribute_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	PyAttribute *self;
	
	self = (PyAttribute *)type->tp_alloc (type, 0);
	return (PyObject *)self;
}

static int
PyAttribute_init (PyAttribute *self, PyObject *args, PyObject *kwds)
{
	unsigned start = 0;
	unsigned int  length = 0;
	AttributeType type  = SCIM_ATTR_NONE;
	unsigned int value = 0;

	if (!PyArg_ParseTuple (args, "|IIII:__init__", &start, &length, &type, &value))
		return -1;

	new (&self->attribute) Attribute (start, length, type, value);

	return 0;
}

static void
PyAttribute_dealloc (PyAttribute *self)
{
	self->attribute.~Attribute ();
	((PyObject *)self)->ob_type->tp_free (self);
}

static PyObject *
PyAttribute_get_start (PyAttribute *self, void *closure)
{
	return PyInt_FromLong ((long)self->attribute.get_start ());
}

static int
PyAttribute_set_start (PyAttribute *self, PyObject *value, void *closure)
{
	if (value == NULL) {
		PyErr_SetString (PyExc_TypeError, 
					"Cannot delete the start attribute");
		return -1;
	}

	if (! PyInt_Check (value)) {
		PyErr_SetString (PyExc_TypeError, 
					"The start attribute value must be an int");
		return -1;
	}
 
	self->attribute.set_start ((uint32)PyInt_AS_LONG (value));

	return 0;
}

static PyObject *
PyAttribute_get_length (PyAttribute *self, void *closure)
{
	
	return PyInt_FromLong ((long)self->attribute.get_length ());
}

static int
PyAttribute_set_length (PyAttribute *self, PyObject *value, void *closure)
{
	if (value == NULL) {
		PyErr_SetString (PyExc_TypeError, 
					"Cannot delete the length attribute");
		return -1;
	}

	if (! PyInt_Check (value)) {
		PyErr_SetString (PyExc_TypeError, 
					"The length attribute value must be an int");
		return -1;
	}
 
	self->attribute.set_length ((uint32)PyInt_AS_LONG (value));

	return 0;
}


static PyObject *
PyAttribute_get_type (PyAttribute *self, void *closure)
{
	
	return PyInt_FromLong ((long)self->attribute.get_type ());
}

static int
PyAttribute_set_type (PyAttribute *self, PyObject *value, void *closure)
{
	if (value == NULL) {
		PyErr_SetString (PyExc_TypeError, 
					"Cannot delete the type attribute");
		return -1;
	}

	if (! PyInt_Check (value)) {
		PyErr_SetString (PyExc_TypeError, 
					"The type attribute value must be an int");
		return -1;
	}
 
	self->attribute.set_type ((AttributeType)PyInt_AS_LONG (value));

	return 0;
}


static PyObject *
PyAttribute_get_value (PyAttribute *self, void *closure)
{
	
	return PyInt_FromLong ((long)self->attribute.get_value ());
}

static int
PyAttribute_set_value (PyAttribute *self, PyObject *value, void *closure)
{
	if (value == NULL) {
		PyErr_SetString (PyExc_TypeError, 
					"Cannot delete the value attribute");
		return -1;
	}

	if (! PyInt_Check (value)) {
		PyErr_SetString (PyExc_TypeError, 
					"The value attribute value must be an int");
		return -1;
	}
 
	self->attribute.set_value ((uint32)PyInt_AS_LONG (value));

	return 0;
}

static PyGetSetDef PyAttribute_getseters[] = {
	{"start", (getter)PyAttribute_get_start, (setter)PyAttribute_set_start,
		"start", NULL},
	{"length", (getter)PyAttribute_get_length, (setter)PyAttribute_set_length,
		"length", NULL},
	{"type", (getter)PyAttribute_get_type, (setter)PyAttribute_set_type,
		"type", NULL},
	{"value", (getter)PyAttribute_get_value, (setter)PyAttribute_set_value,
		"value", NULL},
	{NULL}  /* Sentinel */
};

static PyTypeObject PyAttributeType = {
	PyObject_HEAD_INIT (NULL)
	0,						 				/*ob_size*/
	"scim.Attribute", 						/*tp_name*/
	sizeof (PyAttribute), 					/*tp_basicsize*/
	0,						 				/*tp_itemsize*/
	(destructor)PyAttribute_dealloc,		/*tp_dealloc*/
	0,			  							/*tp_print*/
	0,						 				/*tp_getattr*/
	0,										/*tp_setattr*/
	0,										/*tp_compare*/
	0,			  							/*tp_repr*/
	0,										/*tp_as_number*/
	0,			  							/*tp_as_sequence*/
	0,										/*tp_as_mapping*/
	0,			  							/*tp_hash */
	0,										/*tp_call*/
	(reprfunc)PyAttribute_str,   			/*tp_str*/
	0,					   					/*tp_getattro*/
	0,										/*tp_setattro*/
	0,					 					/*tp_as_buffer*/
	Py_TPFLAGS_DEFAULT,						/*tp_flags*/
	"Attribute objects",		/* tp_doc */
	0,					   		/* tp_traverse */
	0,					   		/* tp_clear */
	0,					   		/* tp_richcompare */
	0,					   		/* tp_weaklistoffset */
	0,					   		/* tp_iter */
	0,					   		/* tp_iternext */
	0,			 				/* tp_methods */
	0,			 				/* tp_members */
	PyAttribute_getseters,		/* tp_getset */
	0,						 	/* tp_base */
	0,						 	/* tp_dict */
	0,						 	/* tp_descr_get */
	0,						 	/* tp_descr_set */
	0,						 	/* tp_dictoffset */
	(initproc)PyAttribute_init,	/* tp_init */
	0,						 	/* tp_alloc */
	PyAttribute_new,			/* tp_new */	
	PyObject_Del,				/* tp_new */	
};



Attribute
Attribute_FromPyObject (PyObject *object)
{
	return ((PyAttribute *)object)->attribute;
}

static void
setint (PyObject *d, const char *name, long value)
{
	PyObject *o = PyInt_FromLong (value);
	if (o && PyDict_SetItemString (d, name, o) == 0) {
		Py_DECREF (o);
	}
}

void init_attribute (PyObject *module)
{
	PyObject *dict;

	if (PyType_Ready (&PyAttributeType) < 0)
		return;

	Py_INCREF (&PyAttributeType);
	PyModule_AddObject (module, "Attribute", (PyObject *)&PyAttributeType);

	dict = PyModule_GetDict (module);

	setint (dict, "ATTR_NONE",		SCIM_ATTR_NONE);
	setint (dict, "ATTR_DECORATE",	SCIM_ATTR_DECORATE);
	setint (dict, "ATTR_FOREGROUND",SCIM_ATTR_FOREGROUND);
	setint (dict, "ATTR_BACKGROUND",SCIM_ATTR_BACKGROUND);
	setint (dict, "ATTR_DECORATE_NONE",		SCIM_ATTR_DECORATE_NONE);
	setint (dict, "ATTR_DECORATE_UNDERLINE",SCIM_ATTR_DECORATE_UNDERLINE);
	setint (dict, "ATTR_DECORATE_HIGLIGHT",	SCIM_ATTR_DECORATE_HIGHLIGHT);
	setint (dict, "ATTR_DECORATE_REVERSE",	SCIM_ATTR_DECORATE_REVERSE);
}
